home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ADA Programming Guide
/
ADA Programming Guide.iso
/
ada_lrm
/
chap01.doc
next >
Wrap
Text File
|
1996-01-30
|
29KB
|
1,190 lines
The following document is a draft of the corresponding chapter of the
version of the Ada Reference Manual produced in response to the Ansi
Canvass. It is given a limited circulation to Ada implementers and to
other groups contributing comments (according to the conventions defined in
RRM.comments). This draft should not be referred to in any publication.
ANSI-RM-01.v23 - Draft Chapter
1 Introduction
version 23
83-02-11
This version has addressed comments up to #5795
1. Introduction
Ada is a programming language designed in accordance with requirements
defined by the United States Department of Defense: the so-called Steelman
requirements. Overall, these requirements call for a language with
considerable expressive power covering a wide application domain. As a
result, the language includes facilities offered by classical languages
such as Pascal as well as facilities often found only in specialized
languages. Thus the language is a modern algorithmic language with the
usual control structures, and with the ability to define types and
subprograms. It also serves the need for modularity, whereby data, types,
and subprograms can be packaged. It treats modularity in the physical
sense as well, with a facility to support separate compilation.
In addition to these aspects, the language covers real-time programming,
with facilities to model parallel tasks and to handle exceptions. It also
covers systems programming; this requires precise control over the
representation of data and access to system-dependent properties. Finally,
both application-level and machine-level input-output are defined.
1.1 Scope of the Standard
This standard specifies the form and meaning of program units written in
Ada. Its purpose is to promote the portability of Ada programs to a
variety of data processing systems.
1.1.1 Extent of the Standard
This standard specifies:
(a) The form of a program unit written in Ada.
(b) The effect of translating and executing such a program unit.
(c) The manner in which program units may be combined to form Ada
programs.
(d) The predefined program units that a conforming implementation must
supply.
(e) The permissible variations within the standard, and the manner in
which they must be specified.
1 - 1
(f) Those violations of the standard that a conforming implementation is
required to detect, and the effect of attempting to translate or
execute a program unit containing such violations.
(g) Those violations of the standard that a conforming implementation is
not required to detect.
1 - 2
This standard does not specify:
(h) The means whereby a program unit written in Ada is transformed into
object code executable by a processor.
(i) The means whereby translation or execution of program units is invoked
and the executing units are controlled.
(j) The size or speed of the object code, or the relative execution speed
of different language constructs.
(k) The form or contents of any listings produced by implementations; in
particular, the form or contents of error or warning messages.
(l) The effect of executing a program unit that contains any violation
that a conforming implementation is not required to detect.
(m) The size of a program or program unit that will exceed the capacity of
a particular conforming implementation.
Where this standard specifies that a program unit written in Ada has an
exact effect, this effect is the operational meaning of the program unit
and must be produced by all conforming implementations. Where this
standard specifies permissible variations in the effects of constituents of
a program unit written in Ada, the operational meaning of the program unit
as a whole is understood to be the range of possible effects that result
from all these variations, and a conforming implementation is allowed to
produce any of these possible effects. Examples of permissible variations
are:
- The represented values of fixed or floating numeric quantities, and
the results of operations upon them.
- The order of execution of statements in different parallel tasks, in
the absence of explicit synchronization.
1.1.2 Conformity of an Implementation With the Standard
A conforming implementation is one that:
(a) Correctly translates and executes legal program units written in Ada,
provided that they are not so large as to exceed the capacity of the
implementation.
(b) Rejects all program units that are so large as to exceed the capacity
of the implementation.
(c) Rejects all program units that contain errors whose detection is
required by the standard.
(d) Supplies all predefined program units required by the standard.
1 - 3
(e) Contains no variations except where the standard permits.
(f) Specifies all such permitted variations in the manner prescribed by
the standard.
1 - 4
1.2 Structure of the Standard
This reference manual contains fourteen chapters, three annexes, three
appendices, and an index.
Each chapter is divided into sections that have a common structure. Each
section introduces its subject, gives any necessary syntax rules, and
describes the semantics of the corresponding language constructs. Examples
and notes, and then references, may appear at the end of a section.
Examples are meant to illustrate the possible forms of the constructs
described. Notes are meant to emphasize consequences of the rules
described in the section or elsewhere. References are meant to attract the
attention of readers to a term or phrase having a technical meaning defined
in another section.
The standard definition of the Ada programming language consists of the
fourteen chapters and the three annexes, subject to the following
restriction: the material in each of the items listed below is
informative, and not part of the standard definition of the Ada programming
language:
- Section 1.3 Design goals and sources
- Section 1.4 Language summary
- The examples, notes, and references given at the end of each section
- Each section whose title starts with the word "Example" or "Examples"
1.3 Design Goals and Sources
Ada was designed with three overriding concerns: program reliability and
maintenance, programming as a human activity, and efficiency.
The need for languages that promote reliability and simplify maintenance is
well established. Hence emphasis was placed on program readability over
ease of writing. For example, the rules of the language require that
program variables be explicitly declared and that their type be specified.
Since the type of a variable is invariant, compilers can ensure that
operations on variables are compatible with the properties intended for
objects of the type. Furthermore, error-prone notations have been avoided,
and the syntax of the language avoids the use of encoded forms in favor of
more English-like constructs. Finally, the language offers support for
separate compilation of program units in a way that facilitates program
development and maintenance, and which provides the same degree of checking
between units as within a unit.
Concern for the human programmer was also stressed during the design.
Above all, an attempt was made to keep the language as small as possible,
given the ambitious nature of the application domain. We have attempted to
1 - 5
cover this domain with a small number of underlying concepts integrated in
a consistent and systematic way. Nevertheless we have tried to avoid the
pitfalls of excessive involution, and in the constant search for simpler
designs we have tried to provide language constructs that correspond
intuitively to what the users will normally expect.
Like many other human activities, the development of programs is becoming
ever more decentralized and distributed. Consequently, the ability to
assemble a program from independently produced software components has been
a central idea in this design. The concepts of packages, of private types,
and of generic units are directly related to this idea, which has
ramifications in many other aspects of the language.
1 - 6
No language can avoid the problem of efficiency. Languages that require
over-elaborate compilers, or that lead to the inefficient use of storage or
execution time, force these inefficiencies on all machines and on all
programs. Every construct of the language was examined in the light of
present implementation techniques. Any proposed construct whose
implementation was unclear or that required excessive machine resources was
rejected.
None of the above design goals was considered as achievable after the fact.
The design goals drove the entire design process from the beginning.
A perpetual difficulty in language design is that one must both identify
the capabilities required by the application domain and design language
features that provide these capabilities. The difficulty existed in this
design, although to a lesser degree than usual because of the Steelman
requirements. These requirements often simplified the design process by
allowing it to concentrate on the design of a given system providing a well
defined set of capabilities, rather than on the definition of the
capabilities themselves.
Another significant simplification of the design work resulted from earlier
experience acquired by several successful Pascal derivatives developed with
similar goals. These are the languages Euclid, Lis, Mesa, Modula, and Sue.
Many of the key ideas and syntactic forms developed in these languages have
counterparts in Ada. Several existing languages such as Algol 68 and
Simula, and also recent research languages such as Alphard and Clu,
influenced this language in several respects, although to a lesser degree
than did the Pascal family.
Finally, the evaluation reports received on an earlier formulation (the
Green language), and on alternative proposals (the Red, Blue, and Yellow
languages), the language reviews that took place at different stages of
this project, and the thousands of comments received from fifteen different
countries during the preliminary stages of the Ada design and during the
ANSI canvass, all had a significant impact on the standard definition of
the language.
1.4 Language Summary
An Ada program is composed of one or more program units. These program
units can be compiled separately. Program units may be subprograms (which
define executable algorithms), package units (which define collections of
entities), task units (which define parallel computations), or generic
units (which define parameterized forms of packages and subprograms).
Each unit normally consists of two parts: a specification, containing the
information that must be visible to other units, and a body, containing the
implementation details, which need not be visible to other units.
This distinction of the specification and body, and the ability to compile
units separately, allows a program to be designed, written, and tested as a
set of largely independent software components.
1 - 7
An Ada program will normally make use of a library of program units of
general utility. The language provides means whereby individual
organizations can construct their own libraries. The text of a separately
compiled program unit must name the library units it requires.
Program Units
A subprogram is the basic unit for expressing an algorithm. There are two
kinds of subprograms: procedures and functions. A procedure is the means
of invoking a series of actions. For example, it may read data, update
variables, or produce some output. It may have parameters, to provide a
controlled means of passing information between the procedure and the point
of call.
1 - 8
A function is the means of invoking the computation of a value. It is
similar to a procedure, but in addition will return a result.
A package is the basic unit for defining a collection of logically related
entities. For example, a package can be used to define a common pool of
data and types, a collection of related subprograms, or a set of type
declarations and associated operations. Portions of a package can be
hidden from the user, thus allowing access only to the logical properties
expressed by the package specification.
A task unit is the basic unit for defining a task whose sequence of actions
may be executed in parallel with those of other tasks. Such tasks may be
implemented on multicomputers, multiprocessors, or with interleaved
execution on a single processor. A task unit may define either a single
executing task or a task type permitting the creation of any number of
similar tasks.
Declarations and Statements
The body of a program unit generally contains two parts: a declarative
part, which defines the logical entities to be used in the program unit,
and a sequence of statements, which defines the execution of the program
unit.
The declarative part associates names with declared entities. For example,
a name may denote a type, a constant, a variable, or an exception. A
declarative part also introduces the names and parameters of other nested
subprograms, packages, task units, and generic units to be used in the
program unit.
The sequence of statements describes a sequence of actions that are to be
performed. The statements are executed in succession (unless an exit,
return, or goto statement, or the raising of an exception, causes execution
to continue from another place).
An assignment statement changes the value of a variable. A procedure call
invokes execution of a procedure after associating any actual parameters
provided at the call with the corresponding formal parameters.
Case statements and if statements allow the selection of an enclosed
sequence of statements based on the value of an expression or on the value
of a condition.
The loop statement provides the basic iterative mechanism in the language.
A loop statement specifies that a sequence of statements is to be executed
repeatedly as directed by an iteration scheme, or until an exit statement
is encountered.
A block statement comprises a sequence of statements preceded by the
declaration of local entities used by the statements.
Certain statements are only applicable to tasks. A delay statement delays
the execution of a task for a specified duration. An entry call statement
is written as a procedure call statement; it specifies that the task
issuing the call is ready for a rendezvous with another task that has this
1 - 9
entry. The called task is ready to accept the entry call when its
execution reaches a corresponding accept statement, which specifies the
actions then to be performed. After completion of the rendezvous, both the
calling task and the task having the entry may continue their execution in
parallel. One form of the select statement allows a selective wait for one
of several alternative rendezvous. Other forms of the select statement
allow conditional or timed entry calls.
1 - 10
Execution of a program unit may encounter error situations in which normal
program execution cannot continue. For example, an arithmetic computation
may exceed the maximum allowed value of a number, or an attempt may be made
to access an array component by using an incorrect index value. To deal
with such error situations, the statements of a program unit can be
textually followed by exception handlers that specify the actions to be
taken when the error situation arises. Exceptions can be raised explicitly
by a raise statement.
Data Types
Every object in the language has a type, which characterizes a set of
values and a set of applicable operations. The main classes of types are
scalar types (comprising enumeration and numeric types), composite types,
access types, and private types.
An enumeration type defines an ordered set of distinct enumeration
literals, for example a list of states or an alphabet of characters. The
enumeration types BOOLEAN and CHARACTER are predefined.
Numeric types provide a means of performing exact or approximate numerical
computations. Exact computations use integer types, which denote sets of
consecutive integers. Approximate computations use either fixed point
types, with absolute bounds on the error, or floating point types, with
relative bounds on the error. The numeric types INTEGER, FLOAT, and
DURATION are predefined.
Composite types allow definitions of structured objects with related
components. The composite types in the language provide for arrays and
records. An array is an object with indexed components of the same type.
A record is an object with named components of possibly different types.
The array type STRING is predefined.
A record may have special components called discriminants. Alternative
record structures that depend on the values of discriminants can be defined
within a record type.
Access types allow the construction of linked data structures created by
the evaluation of allocators. They allow several variables of an access
type to designate the same object, and components of one object to
designate the same or other objects. Both the elements in such a linked
data structure and their relation to other elements can be altered during
program execution.
Private types can be defined in a package that conceals structural details
that are externally irrelevant. Only the logically necessary properties
(including any discriminants) are made visible to the users of such types.
The concept of a type is refined by the concept of a subtype, whereby a
user can constrain the set of allowed values of a type. Subtypes can be
used to define subranges of scalar types, arrays with a limited set of
index values, and records and private types with particular discriminant
values.
1 - 11
Other Facilities
Representation clauses can be used to specify the mapping between types and
features of an underlying machine. For example, the user can specify that
objects of a given type must be represented with a given number of bits, or
that the components of a record are to be represented using a given storage
layout. Other features allow the controlled use of low level, nonportable,
or implementation-dependent aspects, including the direct insertion of
machine code.
Input-output is defined in the language by means of predefined library
packages. Facilities are provided for input-output of values of
user-defined as well as of predefined types. Standard means of
representing values in display form are also provided.
1 - 12
Finally, the language provides a powerful means of parameterization of
program units, called generic program units. The generic parameters can be
types and subprograms (as well as objects) and so allow general algorithms
to be applied to all types of a given class.
1.5 Method of Description and Syntax Notation
The form of Ada program units is described by means of a context-free
syntax together with context-dependent requirements expressed by narrative
rules.
The meaning of Ada program units is described by means of narrative rules
defining both the effects of each construct and the composition rules for
constructs. This narrative employs technical terms whose precise
definition is given in the text (references to the section containing the
definition of a technical term appear at the end of each section that uses
the term).
All other terms are in the English language and bear their natural meaning,
as defined in Webster's Third New International Dictionary of the English
Language.
The context-free syntax of the language is described using a simple variant
of Backus-Naur-Form. In particular,
(a) Lower case words, some containing embedded underlines, are used to
denote syntactic categories, for example:
adding_operator
Whenever the name of a syntactic category is used apart from the
syntax rules themselves, spaces take the place of the underlines
(thus: adding operator).
(b) Boldface words are used to denote reserved words, for example:
array
(c) Square brackets enclose optional items. Thus the two following rules
are equivalent.
return_statement ::= return [expression];
return_statement ::= return; | return expression;
(d) Braces enclose a repeated item. The item may appear zero or more
times; the repetitions occur from left to right as with an equivalent
left-recursive rule. Thus the two following rules are equivalent.
1 - 13
term ::= factor {multiplying_operator factor}
term ::= factor | term multiplying_operator factor
1 - 14
(e) A vertical bar separates alternative items unless it occurs
immediately after an opening brace, in which case it stands for
itself:
letter_or_digit ::= letter | digit
component_association ::= [choice {| choice} =>] expression
(f) If the name of any syntactic category starts with an italicized part,
it is equivalent to the category name without the italicized part.
The italicized part is intended to convey some semantic information.
For example type_name and task_name are both equivalent to name alone.
Note:
The syntax rules describing structured constructs are presented in a form
that corresponds to the recommended paragraphing. For example, an if
statement is defined as
if_statement ::=
if condition then
sequence_of_statements
{elsif condition then
sequence_of_statements}
[else
sequence_of_statements]
end if;
Different lines are used for parts of a syntax rule if the corresponding
parts of the construct described by the rule are intended to be on
different lines. Indentation in the rule is a recommendation for
indentation of the corresponding part of the construct. It is recommended
that all indentations be by multiples of a basic step of indentation (the
number of spaces for the basic step is not defined). The preferred places
for other line breaks are after semicolons. On the other hand, if a
complete construct can fit on one line, this is also allowed in the
recommended paragraphing.
1.6 Classification of Errors
The language definition classifies errors into several different
categories:
(a) Errors that must be detected at compilation time by every Ada
compiler.
These errors correspond to any violation of a rule given in this
reference manual, other than the violations that correspond to (b) or
(c) below. In particular, violation of any rule that uses the terms
must, allowed, legal, or illegal belongs to this category. Any
program that contains such an error is not a legal Ada program; on
1 - 15
the other hand, the fact that a program is legal does not mean, per
se, that the program is free from other forms of error.
(b) Errors that must be detected at run time by the execution of an Ada
program.
The corresponding error situations are associated with the names of
the predefined exceptions. Every Ada compiler is required to generate
code that raises the corresponding exception if such an error
situation arises during program execution. If an exception is certain
to be raised in every execution of a program, then compilers are
allowed (although not required) to report this fact at compilation
time.
1 - 16
(c) Erroneous execution.
The language rules specify certain rules to be obeyed by Ada programs,
although there is no requirement on Ada compilers to provide either a
compilation-time or a run-time detection of the violation of such
rules. The errors of this category are indicated by the use of the
word erroneous to qualify the execution of the corresponding
constructs. The effect of erroneous execution is unpredictable.
(d) Incorrect order dependences.
Whenever the reference manual specifies that different parts of a
given construct are to be executed in some order that is not defined
by the language, this means that the implementation is allowed to
execute these parts in any given order, following the rules that
result from that given order, but not in parallel. Furthermore, the
construct is incorrect if execution of these parts in a different
order would have a different effect. Compilers are not required to
provide either compilation-time or run-time detection of incorrect
order dependences. The foregoing is expressed in terms of the process
that is called execution; it applies equally to the processes that
are called evaluation and elaboration.
If a compiler is able to recognize at compilation time that a construct is
erroneous or contains an incorrect order dependence, then the compiler is
allowed to generate, in place of the code otherwise generated for the
construct, code that raises the predefined exception PROGRAM_ERROR.
Similarly, compilers are allowed to generate code that checks at run time
for erroneous constructs, for incorrect order dependences, or for both.
The predefined exception PROGRAM_ERROR is raised if such a check fails.
1 - 17